﻿using AutoCommunication.Enums;
using AutoCommunication.Helper;
using Newtonsoft.Json;
using System;
using System.ComponentModel;

namespace AutoCommunication.Base
{
    /// <summary>
    /// 变量
    /// </summary>
    public abstract class BaseVariable : INotifyPropertyChanged
    {
        /// <summary>
        /// 变量名子
        /// </summary>
        [DisplayName("1.变量名"), Category("变量信息"), Description("我是变量名字")]
        public string Name { get; set; } = Guid.NewGuid().ToString();
        /// <summary>
        /// 全局唯一变量名：线别名+设备名+变量名
        /// </summary>
        [DisplayName("1.全局唯一变量名"), Category("变量信息"), Description("我是变量名字")]
        public string FullName { get; set; } = Guid.NewGuid().ToString();
        /// <summary>
        /// 变量地址
        /// </summary>
        [DisplayName("变量地址"), Category("变量信息")]
        public abstract string Address { get; set; }

        /// <summary>
        /// <para>在解析变量地址的时候为这个赋值</para>
        /// 起始 字节 地址:用于解析时候用
        /// <para>统一转化为字节</para>
        /// </summary>
        [DisplayName("3.起始地址"), Category("变量信息")]
        public int StartByteAddress { get; set; }

        /// <summary>
        /// <para>在解析变量地址的时候为这个赋值</para>
        /// 如果是位地址,这个表示是第几位
        /// modebus中,这个表示线圈的地址
        /// </summary>
        [DisplayName("4.起始位偏移"), Category("变量信息")]
        public int BitOffset { get; set; }

        /// <summary>
        /// 缩放系数
        /// </summary>
        [DisplayName("缩放系数"), Category("缩放")]
        public double Scale { get; set; } = 1.0;

        /// <summary>
        /// 缩放系数
        /// </summary>
        [DisplayName("偏移量"), Category("缩放")]
        public double Offset { get; set; } = 0;

        /// <summary>
        /// 这个变量占用多少个字节,方便解析,通过这个选择在报文中跳过过少,选择多少字节
        /// </summary>
        [JsonIgnore, Browsable(false)]
        public int Bytelength { get; set; } = 256;

        private object myVar = 0;

        /// <summary>
        /// 变量当前值
        /// </summary>
        [JsonIgnore, Browsable(false)]
        public object Value
        {
            get { return myVar; }
            set
            {
                if (myVar.Equals(value))
                {
                    return;
                }
                myVar = value;
                OnpropertyChanged("Value");
            }
        }

        /// <summary>
        /// 要写入的值
        /// </summary>
        [JsonIgnore, Browsable(false)]
        public double WriteValue { get; set; }

        /// <summary>
        /// 数据类型
        /// </summary>
        [DisplayName("2.0数据类型"), Category("变量信息")]
        public DataTypeEnum DataType { get; set; } = DataTypeEnum.Byte;

        /// <summary>
        /// 读写权限
        /// </summary>
        [DisplayName("5.读写权限"), Category("变量信息")]
        public WriteOrRead WriteOrRead { get; set; } = WriteOrRead.ReadAndWrite;

        #region 报警记录相关

        /// <summary>
        /// 报警类型,是离散报警还是条件报警,多种报警用"|"表示
        /// <para>不能有错误的组合,比如又是上升沿,又是下降沿;比如沿报警和条件报警同时纯在</para>
        /// </summary>
        public AlarmType AlarmType { get; set; } = AlarmType.None;

        /// <summary>
        /// 数据变化通知
        /// </summary>
        [DisplayName("数据变化通知"), DefaultValue(false), Category("数据变化通知")]
        public bool DataChangeEnable { get; set; } = false;

        /// <summary>
        /// 缓存值
        /// </summary>
        [JsonIgnore, Browsable(false)]
        public object CacheValue { get; set; } = "Na";

        /// <summary>
        /// 允许记录
        /// </summary>

        [DisplayName("记录允许"), DefaultValue(false), Category("记录允许")]
        public bool ArchiveEnable { get; set; } = false;

        /// <summary>
        /// 设定限制允许:开启后超过这个范围的值不能被设定
        /// </summary>
        [DisplayName("设定值限定允许"), DefaultValue(false), Category("设定值限定允许")]
        public bool SetLimitEnable { get; set; } = false;

        /// <summary>
        /// 允许写入最大值
        /// </summary>
        [DisplayName("允许写入最大值"), DefaultValue(100f), Category("设定值限定允许")]
        public float SetLimitMax { get; set; } = 100f;

        /// <summary>
        /// 允许写入最小值
        /// </summary>

        [DisplayName("允许写入最小值"), DefaultValue(0f), Category("设定值限定允许")]
        public float SetLimitMin { get; set; } = 0f;

        /// <summary>
        /// 上升沿离散报警缓存值
        /// </summary>
        [JsonIgnore, Browsable(false)] public bool RiseCacheValue { get; set; } = false;

        /// <summary>
        /// 下降沿离散报警缓存值
        /// </summary>
        [JsonIgnore, Browsable(false)] public bool FallCacheValue { get; set; } = true;

        /// <summary>
        /// 离散报警优先级
        /// </summary>
        [JsonProperty("离散报警优先级"), DisplayName("离散报警优先级"), Category("离散报警")]
        public int DiscreteAlarmPriority { get; set; } = 0;

        /// <summary>
        /// 离散报警说明
        /// </summary>
        [JsonProperty("离散报警说明"), DisplayName("离散报警说明"), Category("离散报警")]
        public string DiscreteAlarmNote { get; set; } = "离散报警说明";

        /// <summary>
        /// 低低报警值
        /// </summary>
        [JsonProperty("超低报警设定值"), DisplayName("超低报警设定值"), Category("超低报警")] public float LLowAlarmSetValue { get; set; } = 0f;

        /// <summary>
        /// 低低报警缓存值
        /// </summary>
        [JsonIgnore, Browsable(false)] public float LLowCacheValue { get; set; } = float.MaxValue;

        /// <summary>
        /// 低低报警优先级
        /// </summary>
        [JsonProperty("超低报警优先级"), DisplayName("超低报警优先级"), Category("超低报警")] public int LLowAlarmPriority { get; set; } = 0;

        /// <summary>
        /// 低低报警说明
        /// </summary>

        [JsonProperty("超低报警说明"), DisplayName("超低报警说明"), Category("超低报警")]
        public string LLowAlarmNote { get; set; } = "超低报警说明";

        /// <summary>
        /// 低报警值
        /// </summary>
        [JsonProperty("低报警设定值"), DisplayName("低报警设定值"), Category("低报警")] public float LowAlarmSetValue { get; set; } = 0f;

        /// <summary>
        /// 低报警缓存值
        /// </summary>
        [JsonIgnore, Browsable(false)] public float LowCacheValue { get; set; } = float.MaxValue;

        /// <summary>
        /// 低报警优先级
        /// </summary>
        [JsonProperty("低报警优先级"), DisplayName("低报警优先级"), Category("低报警")] public int LowAlarmPriority { get; set; } = 0;

        /// <summary>
        /// 低报警说明
        /// </summary>

        [JsonProperty("低报警说明"), DisplayName("低报警说明"), Category("低报警")] public string LowAlarmNote { get; set; } = "低报警说明";

        /// <summary>
        /// 高报警设定值
        /// </summary>
        [JsonProperty("高报警设定值"), DisplayName("高报警设定值"), Category("高报警")] public float HighAlarmSetValue { get; set; } = 0f;

        /// <summary>
        /// 高报警缓存值
        /// </summary>
        [JsonIgnore, Browsable(false)] public float HighCacheValue { get; set; } = float.MinValue;

        /// <summary>
        /// 高报警优先级
        /// </summary>
        [JsonProperty("高报警优先级"), DisplayName("高报警优先级"), Category("高报警")] public int HighAlarmPriority { get; set; } = 0;

        /// <summary>
        /// 高报警说明
        /// </summary>
        [JsonProperty("高报警说明"), DisplayName("高报警说明"), Category("高报警")] public string HighAlarmNote { get; set; } = "高报警说明";

        /// <summary>
        /// 高高报警值
        /// </summary>
        [JsonProperty("超高报警设定值"), DisplayName("超高报警设定值"), Category("超高报警")] public float HHighAlarmSetValue { get; set; } = 0f;

        /// <summary>
        /// 高高报警缓存值
        /// </summary>
        [JsonIgnore, Browsable(false)] public float HHighCacheValue { get; set; } = float.MinValue;

        /// <summary>
        /// 高高报警优先级
        /// </summary>
        [JsonProperty("超高报警优先级"), DisplayName("超高报警优先级"), Category("超高报警")] public int HHighAlarmPriority { get; set; } = 0;

        /// <summary>
        /// 高高报警说明
        /// </summary>
        [JsonProperty("超高报警说明"), DisplayName("超高报警说明"), Category("超高报警")] public string HHighAlarmNote { get; set; } = "高高报警说明";

        /// <summary>
        /// 归档周期:多久记录一次
        /// </summary>
        [JsonProperty("记录周期"), DisplayName("记录周期"), Category("记录允许"), Description("归档周期:多久记录一次")]
        public int ArchivePeriod { get; set; }

        /// <summary>
        /// 变量描述
        /// </summary>
        [JsonProperty("变量描述"), DisplayName("变量描述"), Category("变量信息")] public string Description { get; set; } = "这是一个什么样的变量";

        #endregion 报警记录相关

        #region MyRegion

        /// <summary>
        /// 地址解析:非常重要的方法
        /// </summary>
        /// <returns></returns>
        public abstract Result AddressAnalysis();

        /// <summary>
        ///
        /// </summary>

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnpropertyChanged(string name)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

        #endregion MyRegion
    }
}